#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

#define BLINKER_WIFI
#define BLINKER_MIOT_LIGHT
#include <Blinker.h>

char auth[] = "";
char ssid[] = "";
char pswd[] = "";

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        5 // On Trinket or Gemma, suggest changing this to 1

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 150 

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#define DELAYVAL 25 // Time (in milliseconds) to pause between pixels


ESP8266WebServer server(80);

const int led = LED_BUILTIN;

int ledMode=0;
int ledNumber=0;
int red =255;
// 生成 0 到 255 之间的随机绿色分量
int green =255;
// 生成 0 到 255 之间的随机蓝色分量
int blue = 255;

const String postForms = "<!DOCTYPE html>\
<html lang=\"en\">\
<head>\
    <meta charset=\"UTF-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <title>LED Setting</title>\
</head>\
<body>\
    <h2>LED Setting</h2>\
    <form id=\"ledForm\" action=\"/ledSetting\" method=\"POST\">\
        <label for=\"ledNumber\">LED数量:</label>\
        <input type=\"number\" id=\"ledNumber\" name=\"ledNumber\" required><br><br>\
        <label for=\"ledMode\">LED模式:</label>\
        <select id=\"ledMode\" name=\"ledMode\">\
            <option value=\"0\">白色</option>\
            <option value=\"1\">随机色</option>\
            <option value=\"2\">自定义色</option>\
        </select><br><br>\
        <label for=\"ledColor\">LED颜色:</label>\
        <input type=\"color\" id=\"ledColor\" name=\"ledColor\" value=\"#ffffff\"><br><br>\
        <button type=\"submit\">保存设置</button>\
    </form>\
</body>\
</html>\
";

void handleLed()
{

if(ledNumber==0)//关灯
  {
      for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
      pixels.setPixelColor(i, pixels.Color(0, 0, 0));
      pixels.show();   // Send the updated pixel colors to the hardware.
        delay(1); // Pause before next pass through loop
    }
      return;
  }

  if(ledMode==0)//默认开启白灯
  {
    for(int i=0; i<ledNumber; i++) { // For each pixel...
        pixels.setPixelColor(i, pixels.Color(255, 255, 255));
        pixels.show();   // Send the updated pixel colors to the hardware.
        delay(1); // Pause before next pass through loop
    }
  }
  else if(ledMode==1)//随机颜色
  {
    red = random(0, 256);
    // 生成 0 到 255 之间的随机绿色分量
    green = random(0, 256);
    // 生成 0 到 255 之间的随机蓝色分量
    blue = random(0, 256);
        for(int i=0; i<ledNumber; i++) { // For each pixel...
        pixels.setPixelColor(i, pixels.Color(red, green, blue));
        pixels.show();   // Send the updated pixel colors to the hardware.
        delay(1); // Pause before next pass through loop
    }
  }
  else if(ledMode==2)//用户颜色
  {
        for(int i=0; i<ledNumber; i++) { // For each pixel...
        pixels.setPixelColor(i, pixels.Color(red, green, blue));
        pixels.show();   // Send the updated pixel colors to the hardware.
        delay(1); // Pause before next pass through loop
    }
  }
}

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/html", postForms);
  digitalWrite(led, 0);
}

void handleForm() {
  if (server.method() != HTTP_POST) {
    server.send(405, "text/plain", "Method Not Allowed");
  } else {
    String message = "POST form was:\n";
    for (uint8_t i = 0; i < server.args(); i++) { 
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; 
      if(server.argName(i).compareTo("ledNumber")==0)
      {
        ledNumber = atoi(server.arg(i).c_str());
      }
      else if(server.argName(i).compareTo("ledMode")==0)
      {
        ledMode = atoi(server.arg(i).c_str());
      }
      else if(server.argName(i).compareTo("ledColor")==0)
      {
        char red_str[3], green_str[3], blue_str[3];
        // 截取red部分（位置1和2）
        strncpy(red_str, server.arg(i).c_str() + 1, 2);
        red_str[2] = '\0'; // 添加字符串结束符
        // 截取green部分（位置3和4）
        strncpy(green_str, server.arg(i).c_str() + 3, 2);
        green_str[2] = '\0'; // 添加字符串结束符
        // 截取blue部分（位置5和6）
        strncpy(blue_str, server.arg(i).c_str() + 5, 2);
        blue_str[2] = '\0'; // 添加字符串结束符

        // 将十六进制字符串转换为整数
        red = strtol(red_str, NULL, 16);
        green = strtol(green_str, NULL, 16);
        blue = strtol(blue_str, NULL, 16);
      }
    }
    Serial.print("ledNumber:");
    Serial.println(ledNumber);
    Serial.print("ledMode:");
    Serial.println(ledMode);
    Serial.printf("Red: %d\n", red);
    Serial.printf("Green: %d\n", green);
    Serial.printf("Blue: %d\n", blue);
    server.send(200, "text/plain", message);
    handleLed();
  }
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    Number1.print(1);
    if (BLINKER_PROTOCOL_MQTT != NULL) {
        String pub_topic = String("/device/") + Blinker.deviceName() + String("/s");
        String pub_data = "{\"toDevice\":\"the device name you need pub to\",\"data\":{\"hello\":\"blinker\"}}";
        BLINKER_PROTOCOL_MQTT->publish(pub_topic.c_str(), pub_data.c_str());
    }
}
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);
    if(ledNumber!=0)
    {
      ledNumber=0;
    }
    else
    {
      ledNumber=NUMPIXELS;
    }
    handleLed();
}

void miotPowerState(const String & state)
{
    BLINKER_LOG("need set power state: ", state);

    if (state == BLINKER_CMD_ON) {
        BlinkerMIOT.powerState("on");
        BlinkerMIOT.print();
        ledNumber=NUMPIXELS;
    }
    else if (state == BLINKER_CMD_OFF) {
        BlinkerMIOT.powerState("off");
        BlinkerMIOT.print();
        ledNumber=0;
    }
handleLed();
}
void miotQuery(int32_t queryCode)
{
    BLINKER_LOG("MIOT Query codes: ", queryCode);
    BlinkerMIOT.powerState(ledNumber!=0 ? "on" : "off");
    BlinkerMIOT.color(0);
    BlinkerMIOT.mode(0);
    BlinkerMIOT.colorTemp(1000);
    BlinkerMIOT.brightness(1);
    BlinkerMIOT.print();
}
void setup(void) {
  // 初始化串口
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    BLINKER_DEBUG.debugAll();

    // 初始化blinker
    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);
    Button1.attach(button1_callback);
    BlinkerMIOT.attachPowerState(miotPowerState);
    BlinkerMIOT.attachQuery(miotQuery);

  server.on("/", handleRoot);

  server.on("/ledSetting", handleForm);

  server.onNotFound(handleNotFound);

  server.begin();
  Serial.println("HTTP server started");

  #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  // 配置看门狗定时器，超时时间为2秒
  ESP.wdtEnable(WDTO_2S);
}

void loop(void) {
  server.handleClient();
    // 重置看门狗定时器以避免超时
  ESP.wdtFeed();
  Blinker.run();
}
